package ct.view;

import java.beans.PropertyVetoException;

import javax.swing.JDesktopPane;
import javax.swing.JInternalFrame;

/**
 * The internal frame organizer of the {@link MainFrame}.
 * <p>
 * It allows to add frames inside the {@link MainFrame}, manage their location
 * and visibility.
 * 
 * @author zgi3557
 * 
 */
public class MainDesktop extends JDesktopPane {

	/**
	 * For serialization
	 */
	private static final long serialVersionUID = 1L;
	/**
	 * The default offset between two frames at their creation
	 */
	private static final int offset = 30;

	/**
	 * Creates an empty frame organizer
	 */
	public MainDesktop() {
		super();
	}

	/**
	 * Adds a new internal frame in the organizer
	 * 
	 * @param frame
	 *            the frame to add
	 */
	public void addFrame(JInternalFrame frame) {

		// The frame is shift the value of the defined offset from the previous
		// frame
		frame.setLocation(this.getAllFrames().length * offset, this
				.getAllFrames().length
				* offset);
		frame.pack();
		frame.setVisible(true);
		this.add(frame);

		// The frame is selected and moved to front
		selectExplicitFrame(frame);
	}

	/**
	 * Selects and moves to front an existing frame
	 * 
	 * @param frame
	 *            the frame to select
	 */
	public void selectExplicitFrame(JInternalFrame frame) {

		try {
			// Maximizes the frame if iconified
			if (frame.isIcon())
				frame.setIcon(false);
			// Selects and moves to front
			this.moveToFront(frame);
			frame.setSelected(true);
		} catch (PropertyVetoException e) {
		}
	}

	/**
	 * Organizes the existing maximized frames in cascade
	 * <p>
	 * The iconified frames keep their state and are not included in the
	 * operation
	 */
	public void cascade() {

		JInternalFrame[] frames = getAllFrames();
		int nbInternalFrame = frames.length;

		// Computation of the number of maximized frames
		int n = nbInternalFrame;
		for (int i = 0; i < nbInternalFrame; ++i)
			if (frames[i].isIcon())
				--n;

		// Loop on maximized frames
		for (int i = 0, j = n - 1; i < nbInternalFrame; ++i, --j)
			if (!frames[i].isIcon())
				// Sets location and dimension
				frames[i].setBounds(j * offset, j * offset, getWidth() / 2,
						getHeight() / 2);

	}

	/**
	 * Tiles the existing maximized frames
	 * <p>
	 * The iconified frames keep their state and are not included in the
	 * operation
	 */
	public void tile() {

		JInternalFrame[] frames = getAllFrames();
		int nbInternalFrame = frames.length;

		// Computation of the number of maximized frames
		int n = nbInternalFrame;
		for (int i = 0; i < nbInternalFrame; ++i)
			if (frames[i].isIcon())
				--n;

		// Offset to let place to iconified frames
		int below = 0;
		if (n != nbInternalFrame)
			below = 30;

		// Computation of the column number
		if (n == 0)
			return;
		int nbCol = (int) Math.sqrt(n);
		if (n != nbCol * nbCol)
			++nbCol;
		// Computation of the line number
		int nbLin;
		if ((n - 1) / nbCol + 1 < nbCol)
			nbLin = nbCol - 1;
		else
			nbLin = nbCol;

		// Dimensions of the frames
		int dx = getWidth() / nbCol;
		int dy = getHeight() / nbLin - below;

		// Sets location and dimension for all maximized frames
		int k = 0;
		for (int i = 0; i < nbCol; ++i)
			for (int j = 0; j < nbCol && k < n; ++j, ++k)
				frames[i * nbCol + j].setBounds(j * dx, i * dy, dx, dy);

	}

	/**
	 * Iconifies all the frames of the desktop
	 */
	public void iconifyAll() {
		JInternalFrame[] frames = getAllFrames();
		try {
			for (int i = 0; i < frames.length; ++i)
				frames[i].setIcon(true);
		} catch (PropertyVetoException pve) {
		}
	}

}
